/*********************************************************************
* Software License Agreement (BSD License)
* 
*  Copyright (c) 2010, Jack Pien
*  All rights reserved.
* 
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
* 
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
* 
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/
#ifndef __AIRLINK_IMAGE_PUBLISHER_HPP
#define __AIRLINK_IMAGE_PUBLISHER_HPP

#include <stdlib.h>

#define _ERR( msg ) fprintf( stderr, msg )
#define _ASSERT( cond ) assert( cond )

namespace __AirlinkNs {

#define ALINK_CAPTURE_FRAME_SZ_BYTES 32768

    /**
     * Image capture module.
     */
    class AirlinkCapture 
    {
    private:
        /**
         * The temporary memory buffer holding a frame of video
         */
        unsigned char* _pframe;
        unsigned int _pframeSizeBytes;
        unsigned char* _pwrite;

        /**
         * Number of frames captured
         */
        unsigned int _frameCnt;

        /**
         * Initialize the buffer
         *
         * @param size size in bytes 
         */
        void BufferInit( unsigned int size ) {
            if( size > _pframeSizeBytes ) {
                unsigned char* tbuf = (unsigned char*)malloc(size);
                int write_offset = 0;
                if( _pframe != NULL ) {
                    // Copy over the old bits
                    write_offset = (int)(_pwrite-_pframe);
                    memcpy( tbuf, _pframe, write_offset );
                    free( _pframe );
                } 

                // Assign new buffer
                _pframe = tbuf;
                _pframeSizeBytes = size;
                BufferInitPtr();
                _pwrite = _pframe + write_offset;
            } else {
                _ERR( "Why is new frame size smaller than old one?\n" );
            }
        }

        /** 
         * Init the location of write pointer
         */
        void BufferInitPtr() {
            _pwrite = _pframe;
        }

        /**
         * Get the write location of buffer.  Make sure there is enough
         * space in buffer to write.
         *
         * @param nbytes number of bytes we want to write
         * @return the pointer location
         */
        unsigned char* BufferGetPtr( unsigned long long nbytes ) {
            // Make sure there is enough space
            if( (unsigned long long)(_pwrite) + nbytes > 
                (unsigned long long)(_pframe) + _pframeSizeBytes ) {
                // Reallocate a larger buffer
                BufferInit( _pframeSizeBytes * 2 );
            }
            return _pwrite;
        }

        /**
         * Update the pointer
         *
         * @param incBytes the number of bytes to increment the pointer
         */
        void BufferIncPtr( unsigned int incBytes ) {
            _pwrite = _pwrite + incBytes;
        }        
        
    public:
        
        /**
         * Constructor which creates a capture 
         */
        AirlinkCapture() {
            _pframe = NULL;
            _pframeSizeBytes = 0;
            _frameCnt = 0;
            BufferInit( ALINK_CAPTURE_FRAME_SZ_BYTES );
        }
        virtual ~AirlinkCapture() {
            free(_pframe);
        }

        /**
         * Start process
         */
        int Start( int argc, char** argv );        
    };

}



#endif // __AIRLINK_IMAGE_PUBLISHER_HPP
